package com.ruoyi.work.service.impl;

import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.work.domain.WorkProject;
import com.ruoyi.work.domain.vo.*;
import com.ruoyi.work.mapper.WorkReportMapper;
import com.ruoyi.work.service.IWorkReportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WorkReportServiceImpl implements IWorkReportService {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private WorkReportMapper workReportMapper;

    /**
     * 工时投入汇总表（人员工时清单）
     * @param report
     * @param pageNum
     * @param pageSize
     * @param isExport
     * @return
     */
    @Override
    public Map selectUserHourList(UserHourReport report, Integer pageNum, Integer pageSize, boolean isExport) {
        String tabKey = report.getParams().get("TabKey").toString();
        // 获取Tab页
        if (Objects.isNull(tabKey) || StringUtils.isEmpty(tabKey)) {
            throw new ServiceException("获取人员工时清单参数为空，请联系管理员", HttpStatus.ERROR);
        }

        // 根据 日期6.11-6.15时间段 获取所有的项目代码
        List<String> projectCodes = workReportMapper.selectAllProjectCodeByDate(report);
        if (Objects.isNull(projectCodes) || projectCodes.size() == 0) {
            // 没有填报项目（可能放假）,获取所有的项目代码
            projectCodes = workReportMapper.selectFillProjectAll().stream().map(WorkProject::getProjectCode).collect(Collectors.toList());
        }

        Map resMap = new HashMap();
        List<Map<String, Object>> resList = new ArrayList<>();
        switch (tabKey) {
            case "first"://数据汇总
                if (isExport) {
                    // 导出
                    report.setProjectCodeList(projectCodes);
                    resList = workReportMapper.selectAllSumList(report);
                    List<UserHourReport> hourReportList = setData(resList, projectCodes);
                    resMap.put("projectCodes", projectCodes);//项目
                    resMap.put("data", hourReportList);//数据
                } else {
                    // 前端UI分页数据
                    report.setProjectCodeList(projectCodes);
                    PageUtils.startPage(pageNum, pageSize);//设置数据分页
                    resList = workReportMapper.selectAllSumList(report);
                    List<UserHourReport> hourReportList = setData(resList, projectCodes);
                    TableDataInfo page = PageUtils.getDataTable(hourReportList);
                    resMap.put("headers", projectCodes);//动态项目代码
                    resMap.put("data", page);//数据
                }
                break;
            case "second"://部门合计
                if (isExport) {
                    // 导出
                    report.setProjectCodeList(projectCodes);
                    resList = workReportMapper.selectDeptSumList(report);
                    List<UserHourByDeptReport> deptReportList = setDeptData(resList, projectCodes);
                    resMap.put("projectCodes", projectCodes);//项目
                    resMap.put("data", deptReportList);//数据
                } else {
                    // 前端UI分页数据
                    report.setProjectCodeList(projectCodes);
                    PageUtils.startPage(pageNum, pageSize);//设置数据分页
                    resList = workReportMapper.selectDeptSumList(report);
                    List<UserHourByDeptReport> deptReportList = setDeptData(resList, projectCodes);
                    TableDataInfo page = PageUtils.getDataTable(deptReportList);
                    resMap.put("headers", projectCodes);//动态项目代码
                    resMap.put("data", page);//数据
                }
                break;
            case "third"://日期总计
                if (isExport) {
                    // 导出
                    report.setProjectCodeList(projectCodes);
                    resList = workReportMapper.selectDateSumList(report);
                    List<UserHourByDateReport> dateReportList = setDateData(resList, projectCodes);
                    resMap.put("projectCodes", projectCodes);//项目
                    resMap.put("data", dateReportList);//数据
                } else {
                    // 前端UI分页数据
                    report.setProjectCodeList(projectCodes);
                    PageUtils.startPage(pageNum, pageSize);//设置数据分页
                    resList = workReportMapper.selectDateSumList(report);
                    List<UserHourByDateReport> dateReportList = setDateData(resList, projectCodes);
                    TableDataInfo page = PageUtils.getDataTable(dateReportList);
                    resMap.put("headers", projectCodes);//动态项目代码
                    resMap.put("data", page);//数据
                }
                break;
            case "fourth"://项目合计
                if (Objects.nonNull(report.getProjectCodeList()) && report.getProjectCodeList().size() > 0) {
                    projectCodes = report.getProjectCodeList();
                }

                if (isExport) {
                    // 导出
                    report.setProjectCodeList(projectCodes);
                    resList = workReportMapper.selectAllSumList(report);
                    List<UserHourReport> hourReportList = setData(resList, projectCodes);
                    resMap.put("projectCodes", projectCodes);//项目
                    resMap.put("data", hourReportList);//数据
                } else {
                    // 前端UI分页数据
                    report.setProjectCodeList(projectCodes);
                    PageUtils.startPage(pageNum, pageSize);//设置数据分页
                    resList = workReportMapper.selectAllSumList(report);
                    List<UserHourReport> hourReportList = setData(resList, projectCodes);
                    TableDataInfo page = PageUtils.getDataTable(hourReportList);
                    resMap.put("headers", projectCodes);//动态项目代码
                    resMap.put("data", page);//数据
                }
                break;
            default:
                throw new ServiceException("人员工时清单数据错误，请联系管理员", HttpStatus.ERROR);
        }

        return resMap;
    }

    /**
     * 工时投入汇总表（项目工时清单）
     *
     * @param report
     * @return
     */
    @Override
    public List<ProjectHourReport> selectProjectHourList(ProjectHourReport report) {
        List<ProjectHourReport> reportList = new ArrayList<>();

        Long projectId = report.getProjectId();
        List<String> stages = report.getStages();
        List<Long> stageIds = report.getStageIds();
        List<Map<String, Object>> res = workReportMapper.selectProjectHourList(projectId, stages, stageIds);

        // 第一行合計
        Map<String, Object> first = res.stream().filter(a -> "total".equals(a.get("nick_name"))).findFirst().orElse(null);
        if (Objects.nonNull(first)) {
            Double total = (Double) first.get("TOTAL");
            ProjectHourReport hourReport = new ProjectHourReport("合计", "/", "/", "/", total);
            List<Map<String, Double>> resStages = setStage(first, stages);
            hourReport.setStage(resStages);
            reportList.add(hourReport);

            // 移除第一行合计
            res.remove(first);
        }

        // 排序
        res = res.stream().sorted(Comparator.comparing(map -> map.get("dept_name").toString(), Comparator.reverseOrder())).collect(Collectors.toList());

        for (Map<String, Object> map : res) {
            String deptName = String.valueOf(map.get("dept_name"));//模块-部门
            String nickName = String.valueOf(map.get("nick_name"));//姓名
            String userName = String.valueOf(map.get("user_name"));//账号-人员编号
            String postName = String.valueOf(map.get("post_name"));//岗位
            Double sum = (Double) map.get("TOTAL");//个人阶段合计
            ProjectHourReport hourReport = new ProjectHourReport(deptName, nickName, userName, postName, sum);
            List<Map<String, Double>> resStages = setStage(map, stages);
            hourReport.setStage(resStages);
            reportList.add(hourReport);
        }
        return reportList;
    }

    /**
     * 人力成本数据总汇
     *
     * @param report
     * @return
     */
    @Override
    public Map selectCostCollectionList(Integer pageNum, Integer pageSize, CostCollectionReport report, boolean isExport) {
        // 获取所有的阶段
        List<String> stageNameList = workReportMapper.selectWorkStageAll();
        if (Objects.isNull(stageNameList)) {
            throw new ServiceException("获取阶段名称数据错误，请联系管理员", HttpStatus.ERROR);
        }
        // 阶段成本名称
        List<String> stageCostList = stageNameList.stream().map(a -> a + "_cost").collect(Collectors.toList());

        Map resMap = new HashMap();
        report.setStages(stageNameList);
        if (isExport) {
            List<Map<String, Object>> resList = workReportMapper.selectCostCollectionList(report);
            List<CostCollectionReport> reportList = setCostCollection(resList, stageNameList, stageCostList);
            resMap.put("headers1", stageNameList);//阶段
            resMap.put("headers2", stageCostList);//阶段成本
            resMap.put("data", reportList);//数据
        } else {
            PageUtils.startPage(pageNum, pageSize);//设置数据分页
            List<Map<String, Object>> resList = workReportMapper.selectCostCollectionList(report);
            List<CostCollectionReport> reportList = setCostCollection(resList, stageNameList, stageCostList);
            TableDataInfo page = PageUtils.getDataTable(reportList);
            resMap.put("headers1", stageNameList);//阶段
            resMap.put("headers2", stageCostList);//阶段成本
            resMap.put("data", page);//数据
        }
        return resMap;
    }

    /**
     * 人力成本数据明细
     *
     * @param report
     * @return
     */
    @Override
    public Map selectDetailCostList(Integer pageNum, Integer pageSize, CostDetailReport report, boolean isExport) {
        // 获取所有的阶段
        List<String> stageNameList = workReportMapper.selectWorkStageAll();
        if (Objects.isNull(stageNameList)) {
            throw new ServiceException("获取阶段名称数据错误，请联系管理员", HttpStatus.ERROR);
        }

        Map resMap = new HashMap();
        report.setStages(stageNameList);
        if (isExport) {
            List<Map<String, Object>> resList = workReportMapper.selectDetailCostList(report);
            List<CostDetailReport> reportList = setCostDetail(resList, stageNameList);
            resMap.put("headers", stageNameList);//动态项目代码
            resMap.put("data", reportList);//数据
        } else {
            PageUtils.startPage(pageNum, pageSize);//设置数据分页
            List<Map<String, Object>> resList = workReportMapper.selectDetailCostList(report);
            List<CostDetailReport> reportList = setCostDetail(resList, stageNameList);
            TableDataInfo page = PageUtils.getDataTable(reportList);
            resMap.put("headers", stageNameList);//动态项目代码
            resMap.put("data", page);//数据
        }
        return resMap;
    }

    /**
     * 人力成本(项目维度)
     *
     * @param report
     * @return
     */
    @Override
    public List<ProjectCostReport> selectProjectCostList(ProjectCostReport report) {
        return workReportMapper.selectProjectCostList(report);
    }

    /**
     * 项目 人力成本 核算
     *
     * @param report
     * @return
     */
    @Override
    public List<ProjectCheckReport> selectProjectCheckList(ProjectCheckReport report) {
        return workReportMapper.selectProjectCheckList(report);
    }

    /**
     * 人力成本统计表(部门维度)
     *
     * @return
     */
    @Override
    public List<DeptCostReport> selectDeptCostList(DeptCostReport report) {
        List<DeptCostReport> reportList = new ArrayList<>();

        // 获取填报中所有的项目
        List<String> allProjectCodes = report.getProjectCodeList();
        if (Objects.isNull(allProjectCodes)) {
            throw new ServiceException("获取填报项目信息异常，请联系管理员", HttpStatus.ERROR);
        }

        List<Map<String, Object>> res = workReportMapper.selectDeptCostList(report);
        for (Map<String, Object> map : res) {
            String deptName = String.valueOf(map.get("dept_name"));//部门
            String userName = String.valueOf(map.get("user_name"));//人员编号
            String nickName = String.valueOf(map.get("nick_name"));//姓名
            String level = String.valueOf(map.get("post_name"));//职级职等
            BigDecimal amount = new BigDecimal(0);//个人阶段合计

            Double sumHour = 0.0;//个人工时合计
            Map resultMap = setProject(map, allProjectCodes);
            sumHour = (Double) resultMap.get("sumHour");
            List<Map<String, Double>> resProjects = (List<Map<String, Double>>) resultMap.get("projects");

            DeptCostReport deptCostReport = new DeptCostReport(deptName, userName, nickName, level, amount, sumHour);
            deptCostReport.setProjectCost(resProjects);
            reportList.add(deptCostReport);
        }
        return reportList;
    }

    /**
     * 转换数据总汇数据
     *
     * @return
     */
    private List<UserHourReport> setData(List<Map<String, Object>> resList, List<String> projectCodes) {
        List<UserHourReport> res = new ArrayList<>();
        for (Map<String, Object> map : resList) {
            String deptName = String.valueOf(map.get("dept_name"));//部门
            String nickName = String.valueOf(map.get("nick_name"));//姓名
            String userName = String.valueOf(map.get("user_name"));//工号
            String postName = String.valueOf(map.get("post_name"));//岗位性质
            String strDate = String.valueOf(map.get("work_time"));//日期

            // 设置项目
            Map resultMap = setProject(map, projectCodes);
            Double sumProjectHour = (Double) resultMap.get("sumHour");//项目合计工时
            List<Map<String, Double>> resProjects = (List<Map<String, Double>>) resultMap.get("projects");

            UserHourReport deptReport = new UserHourReport(deptName, nickName, userName, postName, strDate, sumProjectHour);
            deptReport.setProjectHours(resProjects);
            res.add(deptReport);
        }
        return res;
    }

    /**
     * 转换部门合计数据
     *
     * @param resList
     * @param projectCodes
     * @return
     */
    private List<UserHourByDeptReport> setDeptData(List<Map<String, Object>> resList, List<String> projectCodes) {
        List<UserHourByDeptReport> res = new ArrayList<>();
        for (Map<String, Object> map : resList) {
            String deptName = String.valueOf(map.get("dept_name"));//部门
            String strDate = String.valueOf(map.get("work_time"));//日期

            // 设置项目
            Map resultMap = setProject(map, projectCodes);
            Double sumProjectHour = (Double) resultMap.get("sumHour");//项目合计工时
            List<Map<String, Double>> resProjects = (List<Map<String, Double>>) resultMap.get("projects");

            UserHourByDeptReport deptReport = new UserHourByDeptReport(deptName, strDate, sumProjectHour);
            deptReport.setProjectHours(resProjects);
            res.add(deptReport);
        }
        return res;
    }

    /**
     * 转换日期合计数据
     *
     * @return
     */
    private List<UserHourByDateReport> setDateData(List<Map<String, Object>> resList, List<String> projectCodes) {
        List<UserHourByDateReport> res = new ArrayList<>();
        for (Map<String, Object> map : resList) {
            String strDate = String.valueOf(map.get("str_date"));//日期

            // 设置项目
            Map resultMap = setProject(map, projectCodes);
            Double sumProjectHour = (Double) resultMap.get("sumHour");//项目合计工时
            List<Map<String, Double>> resProjects = (List<Map<String, Double>>) resultMap.get("projects");

            UserHourByDateReport deptReport = new UserHourByDateReport(strDate, sumProjectHour);
            deptReport.setProjectHours(resProjects);
            res.add(deptReport);
        }
        return res;
    }

    /**
     * 转换人力成本总汇数据
     *
     * @return
     */
    private List<CostCollectionReport> setCostCollection(List<Map<String, Object>> resList, List<String> stageNames, List<String> stageCosts) {
        List<CostCollectionReport> res = new ArrayList<>();
        for (Map<String, Object> map : resList) {
            String projectCode = String.valueOf(map.get("project_code"));//项目代码
            String deptName = String.valueOf(map.get("dept_name"));//部门
            String nickName = String.valueOf(map.get("nick_name"));//姓名
            String userName = String.valueOf(map.get("user_name"));//工号
            String postName = String.valueOf(map.get("post_name"));//岗位

            BigDecimal hourPay = new BigDecimal(String.valueOf(map.get("hour_pay")));//时薪

            // 设置阶段
            Map resultMap = setStageHour(map, stageNames);
            List<Map<String, Double>> stageHour = (List<Map<String, Double>>) resultMap.get("stages");
            Double sumHour = (Double) resultMap.get("sumHour");
            // 设置阶段成本
            Map resultCostMap = setStageHour(map, stageCosts);
            List<Map<String, Double>> stageCost = (List<Map<String, Double>>) resultCostMap.get("stages");
            BigDecimal sumCost = new BigDecimal(String.valueOf(resultCostMap.get("sumHour")));//成本合计

            CostCollectionReport report =
                    new CostCollectionReport(projectCode, deptName, nickName, userName, postName,
                            stageHour, sumHour, hourPay, stageCost, sumCost);
            res.add(report);
        }
        return res;
    }

    /**
     * 转换人力成本明细数据
     *
     * @return
     */
    private List<CostDetailReport> setCostDetail(List<Map<String, Object>> resList, List<String> stageCodes) {
        List<CostDetailReport> res = new ArrayList<>();
        for (Map<String, Object> map : resList) {
            String projectCode = String.valueOf(map.get("project_code"));//项目代码
            String deptName = String.valueOf(map.get("dept_name"));//部门
            String nickName = String.valueOf(map.get("nick_name"));//姓名
            String userName = String.valueOf(map.get("user_name"));//工号
            String postName = String.valueOf(map.get("post_name"));//岗位
            String strDate = String.valueOf(map.get("work_time"));//日期

            // 设置阶段
            Map resultMap = setStageHour(map, stageCodes);
            Double sumStageHour = (Double) resultMap.get("sumHour");//合计工时
            List<Map<String, Double>> resProjects = (List<Map<String, Double>>) resultMap.get("stages");

            CostDetailReport report = new CostDetailReport(projectCode, deptName, nickName, userName, postName, strDate, sumStageHour);
            report.setStage(resProjects);
            res.add(report);
        }
        return res;
    }

    /**
     * 设置项目代码
     *
     * @param map
     * @param allProjects
     * @return
     */
    private Map setProject(Map<String, Object> map, List<String> allProjects) {
        Map resultMap = new HashMap(2);
        Double sumHour = 0.0;//个人工时合计
        List<Map<String, Double>> projectList = new ArrayList<>();
        for (String code : allProjects) {
            Double res = Optional.ofNullable((Double) map.get(code)).orElse(0.0);
            sumHour += res;
            Map<String, Double> resMap = new HashMap<>();
            resMap.put(code, res);
            projectList.add(resMap);
        }
        resultMap.put("projects", projectList);
        resultMap.put("sumHour", sumHour);
        return resultMap;
    }

    /**
     * 设置阶段合计
     *
     * @param map
     * @param list
     * @return
     */
    private Map setStageHour(Map<String, Object> map, List<String> list) {
        Map resultMap = new HashMap(2);
        Double sumHour = 0.0;//个人工时合计
        List<Map<String, Double>> stageList = new ArrayList<>();
        for (String stage : list) {
            Double res = (Double) map.get(stage);
            sumHour += res;
            Map<String, Double> resMap = new HashMap<>();
            resMap.put(stage, res);
            stageList.add(resMap);
        }
        resultMap.put("stages", stageList);
        resultMap.put("sumHour", sumHour);
        return resultMap;
    }

    /**
     * 设置动态阶段
     *
     * @param map    结果集 map
     * @param stages 动态阶段
     */
    private List<Map<String, Double>> setStage(Map<String, Object> map, List<String> stages) {
        List<Map<String, Double>> stageList = new ArrayList<>();
        for (String stage : stages) {
            Double res = (Double) map.get(stage);
            Map<String, Double> resMap = new HashMap<>();
            resMap.put(stage, res);
            stageList.add(resMap);
        }
        return stageList;
    }

    /**
     * 获取已填写的项目
     *
     * @return
     */
    @Override
    public List<WorkProject> selectFillProjectAll() {
        return workReportMapper.selectFillProjectAll();
    }

    @Override
    public List<String> selectWorkStageAll() {
        return workReportMapper.selectWorkStageAll();
    }
}
